package model

import (
	"context"

	"gorm.io/gorm"
)

type TXGenerator struct {
	db *gorm.DB
}

func NewTXGenerator(db *gorm.DB) *TXGenerator {
	return &TXGenerator{
		db: db,
	}
}

func (n *TXGenerator) CreateTX(ctx context.Context) *TX {
	return NewTX(n.db.Begin(), ctx)
}

type TX struct {
	tx  *gorm.DB
	ctx context.Context
}

func NewTX(tx *gorm.DB, ctx context.Context) *TX {
	return &TX{
		tx:  tx,
		ctx: ctx,
	}
}

func (n *TX) GetTX() *gorm.DB {
	return n.tx
}

func (n *TX) Commit() error {
	return n.tx.Commit().Error
}

func (n *TX) Rollback() error {
	return n.tx.Rollback().Error
}

func (n *TX) AutoCommit(Func func() error) error {
	var err error

	defer func() {
		if r := recover(); r != nil {
			n.Rollback()
			panic(r)
		}

		if err != nil {
			n.Rollback()
		} else {
			if commitErr := n.Commit(); commitErr != nil {
				err = commitErr
			}
		}
	}()

	err = Func()
	return err
}
